
package instrumentation;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.HashMap;
import java.util.Set;
import java.util.zip.GZIPOutputStream;
public class BlockClass   implements Serializable {
	private static final long serialVersionUID = 6039856116509927723L;
	private final String cName;
	private final Set<BlockMethodEntry> methods;

	public BlockClass(String cName,Set<Data> fields) {
		this.cName = cName;
		methods = new HashSet<BlockMethodEntry>();
	}

	public String getClzName() {
		return cName;
	}
	public Set<BlockMethodEntry> getBlockMethods() {
		return methods;
	}
	public BlockMethodEntry getMethods(String methodName) {
		for(BlockMethodEntry methodEntry: this.getBlockMethods()){
			if(methodEntry.getFullQualifiedName().equals(methodName))
				return methodEntry;
		}
		return null;
	}

	void addMethod(BlockMethodEntry m) {
			methods.add(m);
	}
	public void write(File baseDir,String cName) {
		ObjectOutput oo = null;
		try {

			final File file = new File(baseDir, cName.replace('.', File.separatorChar) + ".wgz");
			oo = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(file)));
			oo.writeObject(this);
		} catch(IOException e) {
		} finally {
			if(oo != null)
				try {
					oo.close();
				} catch(IOException e) {
				}
		}
	}

	public String blockToString() {
		StringBuilder sb = new StringBuilder();
		Map<Integer, Condition> mapBranchCondition=new HashMap<Integer, Condition>();
		Map<Integer, String> methodBranchCondition=new HashMap<Integer, String>();
		BlockClass bc = (BlockClass) this;
		for(BlockMethodEntry b : bc.getBlockMethods()) {
			Set<Condition> branches=b.getCondition();
			for(Condition c:branches){
				if(c instanceof ConditionIf ){
					mapBranchCondition.put(c.getBranchId(), c);
					methodBranchCondition.put(c.getBranchId(), b.getFullQualifiedName());
				}
				else{
					ConditionSwitch cSwitch=(ConditionSwitch) c;
					Map<Integer,Integer> cases=cSwitch.getCases();
					for(Integer branchID : cases.keySet()) {											
						mapBranchCondition.put(branchID, c);
						methodBranchCondition.put(branchID, b.getFullQualifiedName());
					}
					mapBranchCondition.put(cSwitch.getDefaultCase(), c);
					methodBranchCondition.put(cSwitch.getDefaultCase(), b.getFullQualifiedName());
				}
			}
		}
//		BlockFunctionEntry m = (BlockFunctionEntry) this;
		 TreeMap<Integer,Condition> sorted_map = new TreeMap<Integer,Condition>(mapBranchCondition);
	       for (Map.Entry<Integer, Condition> entry : sorted_map.entrySet()) {
				Condition c= sorted_map.get(entry.getKey());
				if(c instanceof ConditionIf ){
				
					System.out.print(methodBranchCondition.get(((ConditionIf) c).getBranchId()) + "\t[branch:"+((ConditionIf) c).getBranchId() + "] ");
					System.out.println(c.toString()+ " ");
				}
				else{
					  System.out.print(methodBranchCondition.get(entry.getKey()) + "\t[branch:"+entry.getKey().toString() + "] ");
					  System.out.print(c.toString()+ " ");
					  System.out.println("\tcases: " + ((ConditionSwitch) c).getCases().get(entry.getKey()));

					}
				

	       }
	       System.out.println( bc.getClzName()+" ("+ mapBranchCondition.size() +")"+ mapBranchCondition.keySet());
//		sb.append(bc.getClzName()+"\n");
//		for(BlockMethodEntry b : bc.getBlockMethods()) {
//			sb.append("\t"+b.getFullQualifiedName()+"\n");
////			System.out.println("\t"+b.getFullQualifiedName()+"\n");
//			Set<Condition> branches=b.getCondition();
//			List<Condition> orders = new ArrayList<Condition>(branches);
//			Collections.sort(orders,Condition.SORT_MEMBERS_BY_BRANCHID);
//            for(int brId=0; brId<orders.size();brId++ ){
//            	Condition c= orders.get(brId);
////            	if(c instanceof ConditionIf )
//            		sb.append("\t"+orders.get(brId)+"\n");
////            	else{
// //           		sb.append("\t"+orders.get(brId)+"\n");        		
////					ConditionSwitch cSwitch=(ConditionSwitch) c;
////					Map<Integer,Integer> cases=cSwitch.getCases();
////					for(Integer caseID:cases.keySet())
////						sb.append("\tcases: " + cases.get(caseID)+"\n");
// //           	}
//            }
//           }
		return sb.toString();
	}
	@Override
	public String toString(){
		return blockToString();
	}





}
